package com.gengzp.common.utils;

import jakarta.annotation.PostConstruct;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @ClassName ExecutorUtils
 * @Description 线程工具类
 * @Author gengzp
 * @Date 2025/6/2 22:18
 */
@Component
public class ExecutorUtils {

    private static final Logger logger = LoggerFactory.getLogger(ExecutorUtils.class);

    /**
     * ExecutorService
     */
    private static ExecutorService executorService;

    /**
     * 构造方法私有化, 禁止外部创建实例
     */
    private ExecutorUtils() {
    }

    /**
     * Spring容器启动时,执行@PostConstruct方法,初始化线程池
     */
    @PostConstruct
    private void init() {
        executorService = new ThreadPoolExecutor(
                3,
                16,
                30,
                TimeUnit.SECONDS,
                new ArrayBlockingQueue<>(150),
                new CustomThreadFactory("Executor-Thread-gzp"),
                new ThreadPoolExecutor.CallerRunsPolicy());
    }

    /**
     * 获取线程池,为了线程安全,使用 synchronized 进行修饰
     */
    public synchronized static ExecutorService getThreadPool() {
        return executorService;
    }

    /**
     * 关闭线程池
     */
    public static void shutdownThreadPool() {
        if (executorService != null && !executorService.isShutdown()) {
            executorService.shutdown();
            try {
                if (!executorService.awaitTermination(60, TimeUnit.SECONDS)) {
                    executorService.shutdownNow();
                    if (!executorService.awaitTermination(60, TimeUnit.SECONDS)) {
                        logger.error("Pool did not terminate");
                    }
                }
            } catch (InterruptedException ie) {
                executorService.shutdownNow();
                Thread.currentThread().interrupt();
            }
        }
    }

    /**
     * 自定义线程工厂
     */
    private static class CustomThreadFactory implements ThreadFactory {
        private final String namePrefix;
        private final AtomicInteger nextId = new AtomicInteger(1);

        CustomThreadFactory(String namePrefix) {
            this.namePrefix = namePrefix;
        }

        @Override
        public Thread newThread(Runnable task) {
            String name = namePrefix + nextId.getAndIncrement();
            return new Thread(null, task, name);
        }
    }

}
